﻿#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"

//增加节点(空间)并初始化
SListNode* SLTBuyNode(SLTDataType x)
{
	//开辟一个节点的空间
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	//判断是否开辟成功
	if (newnode == NULL)//失败
	{
		perror("malloc:");
		exit(1);
	}
	//成功就先把节点数据设置好，再返回这个新节点的地址
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}


//尾插数据
void SLTPushBack(SListNode** pphead, SLTDataType x)
{
	assert(pphead);//不能为空，否则就会对空指针解引用，从而报错
	//首先判断是否为空，再根据判断的情况来尾插
	if (*pphead == NULL)//指向头节点的指针为空，也就是链表为空
	{
		*pphead = SLTBuyNode(x);
	}
	else
	{
		SListNode* newnode = *pphead;//头指针
		while (newnode->next)
		{
			newnode = newnode->next;
		}
		//此时newnode为尾节点
		newnode->next = SLTBuyNode(x);
	}
}


//打印节点数据
void SLTPrint(SListNode* phead)
{
	SListNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}


//头插数据
void SLTPushFront(SListNode** pphead, SLTDataType x)
{
	assert(pphead);
	//判断是否为空
	if (*pphead == NULL)
	{
		*pphead = SLTBuyNode(x);
	}
	else
	{
		SListNode* pcur = *pphead;
		*pphead = SLTBuyNode(x);
		(*pphead)->next = pcur;
	}
}


//查找数据
SListNode* SLTFind(SListNode* phead, SLTDataType x)
{
	assert(phead);
	SListNode* plist = phead;
	while (plist)
	{
		if (plist->data == x)
		{
			return plist;
		}
		plist = plist->next;
	}
	return NULL;
}


//尾删数据
void SLTPopBack(SListNode** pphead)
{
	assert(pphead && *pphead);//*pphead不能为空，否则就是空链表
	//注意操作符的优先级
	if ((*pphead)->next == NULL)//只有一个节点
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SListNode* plist = *pphead;
		//找到尾节点的前一个节点
		while (plist->next->next)
		{
			plist = plist->next;
		}
		free(plist->next);
		plist->next = NULL;
	}
}


//头删数据
void SLTPopFront(SListNode** pphead)
{
	assert(pphead && *pphead);
	//注意操作符的优先级
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SListNode* pcur = *pphead;
		*pphead = (*pphead)->next;
		free(pcur);
	}
}


//在指定位置之前插⼊数据
void SLTInsert(SListNode** pphead, SListNode* pos, SLTDataType x)
{
	assert(pphead && *pphead);
	assert(pos);//这个位置肯定要存在
	//先判断插入的位置
	if (*pphead == pos)
	{
		//头插
		SLTPushFront(pphead, x);
	}
	else
	{
		SListNode* pcur = SLTBuyNode(x);//要插入的节点
		SListNode* prev = *pphead;
		while (prev->next != pos)//找到pos的前一个节点
		{
			prev = prev->next;
		}
		prev->next = pcur;
		pcur->next = pos;
	}
}


//在指定位置之后插入数据
void SLTInsertAfter(SListNode* pos, SLTDataType x)
{
	assert(pos);
	SListNode *pcur = SLTBuyNode(x);
	//下面的顺序不能反过来
	pcur->next = pos->next;
	pos->next = pcur;
}


//删除pos节点
void SLTErase(SListNode** pphead, SListNode* pos)
{
	assert(pphead && *pphead);
	assert(pos);
	//先判断是否为头节点
	if (pos == *pphead)
	{
		//头删
		SLTPopFront(pphead);
	}
	else
	{
		SListNode* prev = *pphead;
		//找到pos前一个节点
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}


//删除pos之后的节点
void SLTEraseAfter(SListNode* pos)
{
	assert(pos && pos->next);//如果pos后面没节点了，就不能删了
	SListNode* pcur = pos->next;
	pos->next = pos->next->next;
	free(pcur);
	pcur = NULL;
}


//销毁链表
void SListDesTroy(SListNode** pphead)
{
	assert(pphead && *pphead);
	SListNode* pcur = *pphead;
	while (pcur)
	{
		SListNode* nextNode = pcur->next;//先把pcur的下一个节点的地址存起来
		free(pcur);//释放掉pcur的节点空间
		pcur = nextNode;//把pcur指向next
	}
	*pphead = NULL;
}